//
//  BuddyListPacketCenter.m
//  HiQServer
//
//  Created by shoguncao on 12-8-1.
//  Copyright (c) 2012年 __MyCompanyName__. All rights reserved.
//

#import "BuddyListPacketCenter.h"
#import "MysqlDB.h"
#import "MacroComd.h"
#import "MiniSocket.h"
#import "MainSocketDelegate.h"

@implementation BuddyListPacketCenter

- (id)init
{
    return [super init];
}

- (void)dealloc
{
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

-(void)MessageDispatch: (SockPacket *)packet
{
    BUDDYLISTREQUESTHRD *request = (BUDDYLISTREQUESTHRD *)[packet.packetContent bytes]; // 收到的包转换成buddyList查询包头
    
    switch (request->operation) 
    {
        case OP_BUDDY_LIST_REQUEST: // 对拉取好友列表请求的响应
        {
            NSInteger qqNum = request->qq_num;
            GCDAsyncSocket *socket = [packet subAsynSocket];
            [self sendBuddyList:qqNum socket:socket];
        }
            
        default:
        {
            UTF8Char * bytes = (UTF8Char *)[packet.packetContent bytes] + 8;
            NSUInteger subFun =*((NSUInteger *) bytes); 
            NSString *msg = [[NSString alloc] initWithBytes:(bytes+8) 
                                                     length:(packet.packetLen-16) encoding:NSUTF8StringEncoding];
            if(msg)
            {
                NSLog(@"log delegate message--->收到---%@ subfun is %lu\r\n",msg,subFun);
                NSUInteger length = packet.packetLen;
                NSMutableData *data = [NSMutableData dataWithBytes:&(length) length:sizeof(NSUInteger)];
                [data appendBytes:[packet.packetContent bytes] length:length];
                /*dispatch_async(dispatch_get_main_queue(), ^{ 
                 [packet.subAsynSocket writeData:data withTimeout:-1 tag:0];
                 });*/
                [packet.subAsynSocket writeData:data withTimeout:-1 tag:0];
            }
            else
            {
                NSLog(@"Error converting received data into UTF-8 String");
            }
            break;
            
        }
    }
    
}

- (void)notifySendBuddyList:(NSNotification *)notification
{
    NSDictionary *dic = [notification userInfo];
    NSNumber *qqNum = [dic objectForKey:@"qqNum"];
    GCDAsyncSocket *socket = [dic objectForKey:@"socket"];
    
    [self sendBuddyList:[qqNum intValue] socket:socket];
}

// 发送查询回复包
- (void)sendBuddyList:(NSInteger)qqNum socket:(GCDAsyncSocket *)socket
{
    MysqlDB *serverConnect = [[MysqlDB alloc] init];
    [serverConnect connectHost:hostIp connectUser:userName connectPassword:password connectName:dbName];
    NSString *command;
    
    NSMutableArray *buddyListUserId = [[NSMutableArray alloc] init];
    NSMutableArray *buddyListUserName = [[NSMutableArray alloc] init];
    NSMutableArray *buddyListUserImage = [[NSMutableArray alloc] init];
    NSMutableArray *buddyListUserStatus = [[NSMutableArray alloc] init];
    NSMutableArray *buddyListUserListenPort = [[NSMutableArray alloc] init];
    NSMutableArray *buddyListUserIp = [[NSMutableArray alloc] init];
    // 查询 tbFriends 表
    command = [[NSString alloc] initWithFormat:@"SELECT * FROM tbFriends WHERE UserId = '%ld'", qqNum];
    NSMutableArray *buddyList = [serverConnect doDataQuery:command];
    
    NSInteger isError = ERR_NO_ERROR;  // 如果访问数据库返回的数据正确，则设此标志为 ERR_NO_ERROR，否则置为相应的错误标志
    
    if ([buddyList count] == 0)
    {
        isError = ERR_NO_BUDDY;
    }
    else 
    {
        // 查询 tbUser 表
        for (NSInteger i=0; i<[buddyList count]; ++i)
        {
            NSMutableArray *buddy, *buddyUserInfo, *buddyUser;
            NSString *buddyId, *buddyUserName, *buddyUserImage;
            NSNumber *status;
            
            buddy = [buddyList objectAtIndex:i];
            if ([buddy count] <= COLUM_OF_USERID_IN_TBFRIENDS)
            {
                isError = ERR_TBFRIENDS_USERID;
                break;
            }
            buddyId = [buddy objectAtIndex:COLUM_OF_USERID_IN_TBFRIENDS];
            [buddyListUserId addObject:buddyId];
            command = @"SELECT * FROM tbUser WHERE UserId = '";
            command = [command stringByAppendingString:buddyId];
            command = [command stringByAppendingString:@"';"];
            buddyUserInfo = [serverConnect doDataQuery:command];
            if ([buddyUserInfo count] != 1) // 查无此人，或者这个 id 有多个记录(不可能，除非数据库出错)
            {
                isError = ERR_TBUSER_USER;
                break;
            }
            buddyUser = [buddyUserInfo objectAtIndex:0];
            if ([buddyUser count] <= COLUM_OF_USERNAME_IN_TBUSER)
            {
                isError = ERR_TBUSER_USERNAME;
                break;
            }
            buddyUserName = [buddyUser objectAtIndex:COLUM_OF_USERNAME_IN_TBUSER];  // 取出记录的第二列
            [buddyListUserName addObject:buddyUserName];
            if ([buddyUser count] <= COLUM_OF_USERIMAGE_IN_TBUSER)
            {
                isError = ERR_TBUSER_USERIMAGE;
                break;
            }
            buddyUserImage =  [buddyUser objectAtIndex:COLUM_OF_USERIMAGE_IN_TBUSER];
            [buddyListUserImage addObject:buddyUserImage];
            MiniSocket *sock = [self isBuddyOnline:[buddyId intValue]];
            if (sock == nil)   // 好友是否在线
            {
                status = [[NSNumber alloc] initWithInt:BUDDY_STATUS_OFFLINE];
                [buddyListUserStatus addObject:status];
                
                NSNumber *listenPort = [[NSNumber alloc] initWithInt:0];
                [buddyListUserListenPort addObject:listenPort];
                
                NSData *ipData = [[NSData alloc] init];
                [buddyListUserIp addObject:ipData];
            }
            else
            {
                status = [[NSNumber alloc] initWithInt:BUDDY_STATUS_ONLINE];
                [buddyListUserStatus addObject:status];
                
                NSNumber *listenPort = [[NSNumber alloc] initWithInt:(int)sock.listenPort];
                [buddyListUserListenPort addObject:listenPort];
                
                NSString *ipStr = [sock.miniAsynSocket connectedHost];
                [buddyListUserIp addObject:ipStr];
            }
        }
    }
    
    // 向客户端发送 UserId 和 UserName
    NSData *reply = [[NSData alloc] init];
    reply = [self createBuddyListReplyPacket:isError userCount:[buddyListUserId count] userId:buddyListUserId userName:buddyListUserName userImage:buddyListUserImage userStatus:buddyListUserStatus userListenPort:buddyListUserListenPort userIp:buddyListUserIp];  // 产生查询回复包
    NSInteger sendLength = [reply length];
    NSMutableData *sendData = [[NSMutableData alloc] initWithBytes:&sendLength length:sizeof(sendLength)];
    [sendData appendData:reply];
    [socket writeData:sendData withTimeout:-1 tag:0];
    [serverConnect disconnect];
}

// 产生查询回复包
- (NSData *)createBuddyListReplyPacket:(NSInteger)isError userCount:(NSInteger)count userId:(NSMutableArray *)userIdArray userName:(NSMutableArray *)userNameArray userImage:(NSMutableArray *)userImageArray userStatus:(NSMutableArray *)userStatusArray userListenPort:(NSMutableArray *)userListenPort userIp:(NSMutableArray *)userIpArray
{
    BUDDYLISTREPLYHRD *replyHRD;
    NSInteger packetLength = 0;
    if (isError != ERR_NO_ERROR)
    {
        packetLength = sizeof(BUDDYLISTREPLYHRD);
        replyHRD = (BUDDYLISTREPLYHRD *)NewPtr(packetLength);
        
        replyHRD->type = CMD_FUN_BUDDYLIST;
        replyHRD->operation = OP_BUDDY_LIST_REPLY;
        replyHRD->error = isError;
        replyHRD->count = count;
        replyHRD->userid_len = 0;
        replyHRD->username_len = 0;
        replyHRD->userimage_len = 0;
        replyHRD->userstatus_len = 0;
        replyHRD->userlistenport_len = 0;
        replyHRD->userip_len = 0;
    }
    else
    {
        NSData *userIdData = [NSKeyedArchiver archivedDataWithRootObject:userIdArray];
        NSData *userNameData = [NSKeyedArchiver archivedDataWithRootObject:userNameArray];
        NSData *userImageData = [NSKeyedArchiver archivedDataWithRootObject:userImageArray];
        NSData *userStatusData = [NSKeyedArchiver archivedDataWithRootObject:userStatusArray];
        NSData *userListenPortData = [NSKeyedArchiver archivedDataWithRootObject:userListenPort];
        NSData *userIpData = [NSKeyedArchiver archivedDataWithRootObject:userIpArray];
        
        packetLength = sizeof(BUDDYLISTREPLYHRD) + [userIdData length] + [userNameData length] + [userImageData length] + [userStatusData length] + [userListenPortData length] + [userIpData length];
        replyHRD = (BUDDYLISTREPLYHRD *)NewPtr(packetLength);
        
        replyHRD->type = CMD_FUN_BUDDYLIST;
        replyHRD->operation = OP_BUDDY_LIST_REPLY;
        replyHRD->error = ERR_NO_ERROR;
        replyHRD->count = count;
        replyHRD->userid_len = [userIdData length];
        replyHRD->username_len = [userNameData length];
        replyHRD->userimage_len = [userImageData length];
        replyHRD->userstatus_len = [userStatusData length];
        replyHRD->userlistenport_len = [userListenPortData length];
        replyHRD->userip_len = [userIpData length];
        
        char *replyUserId = (char *)(replyHRD) + sizeof(BUDDYLISTREPLYHRD);
        [userIdData getBytes:replyUserId length:[userIdData length]];
        
        char *replyUserName = (char *)(replyHRD) + sizeof(BUDDYLISTREPLYHRD) + [userIdData length];
        [userNameData getBytes:replyUserName length:[userNameData length]];
        
        char *replyUserImage = (char *)(replyHRD) + sizeof(BUDDYLISTREPLYHRD) + [userIdData length] + [userNameData length];
        [userImageData getBytes:replyUserImage length:[userImageData length]];
        
        char *replyUserStatus = (char *)(replyHRD) + sizeof(BUDDYLISTREPLYHRD) + [userIdData length] + [userNameData length] + [userImageData length];
        [userStatusData getBytes:replyUserStatus length:[userStatusData length]];
        
        char *replyUserListenPort = (char *)(replyHRD) + sizeof(BUDDYLISTREPLYHRD) + [userIdData length] + [userNameData length] + [userImageData length] + [userStatusData length];
        [userListenPortData getBytes:replyUserListenPort length:[userListenPortData length]];
        
        char *replyUserIp = (char *)(replyHRD) + sizeof(BUDDYLISTREPLYHRD) + [userIdData length] + [userNameData length] + [userImageData length] + [userStatusData length] + [userListenPortData length];
        [userIpData getBytes:replyUserIp length:[userIpData length]];
    }
    NSData *reply = [[NSData alloc] initWithBytes:replyHRD length:packetLength];
    DisposePtr((char *)replyHRD);
    return reply;
}

// 判断 userId 对应的用户是否在线
- (MiniSocket *)isBuddyOnline:(NSInteger)userId
{
    @synchronized([MainSocketDelegate connectedSocketsQueue])
    {
        // 遍历 connectedSocketQueue，找到该好友的 _sock
        for (MiniSocket *_sock in [MainSocketDelegate connectedSocketsQueue]) 
        {
            if (_sock.userId == userId)
            {
                return _sock;
            }
        }
        return nil;
    }
}

@end
